package com.mueeee.webspringboot3;

import com.mueeee.webspringboot3.conf.AppConfig;
import com.mueeee.webspringboot3.conf.ApplicationService;
import com.mueeee.webspringboot3.model.entity.NumberCode;
import com.mueeee.webspringboot3.repository.NumberRepository;
import com.mueeee.webspringboot3.utils.OpenWebpageUtils;
import com.mueeee.webspringboot3.utils.SpringUtil;
import com.mueeee.webspringboot3.utils.WinProxyUtils1;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.regex.Pattern;

/**
 * JavaFx Application
 *
 * 开发时如果直接启动这个类，会报找不到组件或其他错误信息，需要在IDEA启动项中配置如下jvm参数
 * --module-path "D:\dev\javafx-sdk-15.0.1\lib" --add-modules javafx.controls,javafx.fxml
 * 关于这个问题，还有另一种解决方案，另外创建一个主类，然后类调用默认的启动类。请运行：DesktopJavaFxApp
 *
 * 官方文档：https://openjfx.io/openjfx-docs/
 * 错误原因：https://my.oschina.net/tridays/blog/2222909
 */
//@Service
public class App extends Application {
    private static final Logger log = LoggerFactory.getLogger(App.class);

//    @Value("${server.port}")
//    private int serverPort;
    private static Scene scene;
    private static ConfigurableApplicationContext context;

//    public App() {
//        // 解决Linux上编译为native-image时运行错误：
//        String osName = System.getProperty("os.name", "");
//        if (Pattern.matches("Linux.*", osName)) {
//            System.setProperty("prism.forceGPU", "true");
//        }
//        // Init & Launch
//        AppConfig.init();
//        launch();
//    }

    public void addMenu(Stage primaryStage) {
        final Environment bean = SpringUtil.getBean(Environment.class);
        final SpringUtil springUtil = SpringUtil.getBean(SpringUtil.class);
        final ApplicationService applicationService = SpringUtil.getBean(ApplicationService.class);
        final NumberRepository numberRepository = SpringUtil.getBean(NumberRepository.class);
        final String serverPort = bean.getProperty("server.port");
        final int mobProxyPort = Integer.parseInt(bean.getProperty("mob.proxy.port", "12511"));

        BorderPane root = new BorderPane();
        scene.setRoot(root);

        MenuBar menuBar = new MenuBar();
        menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
        root.setTop(menuBar);

        Menu showMenu = new Menu("显示");
        final MenuItem e2 = new MenuItem("展示数据");
        showMenu.getItems().add(e2);
        e2.setOnAction(e -> {
            final Iterable<NumberCode> all = numberRepository.findAll();
            final long count = numberRepository.count();
            log.info("size:{}", count);
            if (all.iterator().hasNext()) {
                final Iterator<NumberCode> iterator = all.iterator();
                final NumberCode next = iterator.next();
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setHeaderText(null);
                alert.setContentText(next.toString());
                alert.show();
            }
        });

        Menu controlMenu = new Menu("控制");

        MenuItem startMenuItem = new MenuItem("启动应用");
        MenuItem openMenuItem = new MenuItem("打开页面");
        MenuItem exitMenuItem = new MenuItem("关闭应用");
        MenuItem restartMenuItem = new MenuItem("重启应用");
        exitMenuItem.setOnAction(actionEvent -> Platform.exit());

        //Creating the mouse event handler
        EventHandler<ActionEvent> startEventHandler = e -> {
            try {
                stop();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            applicationService.restart(springUtil);
        };
        //Creating the mouse event handler
        EventHandler<ActionEvent> restartEventHandler = e -> {
            applicationService.restart(springUtil);
            try {
                stop();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };
        //Creating the mouse event handler
        EventHandler<ActionEvent> openEventHandler = e -> {
            log.info("serverPort:{}", serverPort);
            OpenWebpageUtils.open("http://127.0.0.1:" + serverPort + "/#/about?autoclose");
        };
        //Creating the mouse event handler
        EventHandler<ActionEvent> exitEventHandler = e -> {
            System.exit(0);
        };
        //Registering the event filter
        startMenuItem.setOnAction(startEventHandler);
        openMenuItem.setOnAction(openEventHandler);
        restartMenuItem.setOnAction(restartEventHandler);

        exitMenuItem.setOnAction(exitEventHandler);


        controlMenu.getItems().addAll(startMenuItem, openMenuItem,
                new SeparatorMenuItem(), exitMenuItem, restartMenuItem);

        Menu proxyMenu = new Menu("代理");
        MenuItem testProxyMenuItem = new MenuItem("测试代理");
        proxyMenu.getItems().add(testProxyMenuItem);
        EventHandler<ActionEvent> testProxyEventHandler = e -> {
            OpenWebpageUtils.open("https://www.runoob.com/?testBing");
        };
        testProxyMenuItem.setOnAction(testProxyEventHandler);

        EventHandler<ActionEvent> openProxyEventHandler = e -> {
            try {
                final String proxyHost = "127.0.0.1";
                WinProxyUtils1.setProxy(proxyHost, mobProxyPort);
                final String message = "代理开启成功(" + proxyHost + ":" + mobProxyPort + ")";
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setHeaderText(null);
                alert.setContentText(message);
                alert.show();
                log.info("openProxyEventHandler:message:{}", message);
            } catch (Exception e1) {
                log.error("error", e1);
            }
        };

        EventHandler<ActionEvent> closeProxyEventHandler = e -> {
            try {
                WinProxyUtils1.clearProxy();
                final String message = "代理关闭成功";
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setHeaderText(null);
                alert.setContentText(message);
                alert.show();
                log.info("closeProxyEventHandler:message:{}", message);
            } catch (Exception e1) {
                log.error("error", e1);
            }
        };

        MenuItem openProxyMenuItem = new MenuItem("开启代理");
        openProxyMenuItem.setOnAction(openProxyEventHandler);
        proxyMenu.getItems().add(openProxyMenuItem);


        MenuItem closeProxyMenuItem = new MenuItem("关闭代理");
        closeProxyMenuItem.setOnAction(closeProxyEventHandler);
        proxyMenu.getItems().add(closeProxyMenuItem);

        menuBar.getMenus().addAll(controlMenu, proxyMenu, showMenu);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        // 解决Linux上编译为native-image时运行错误：
        String osName = System.getProperty("os.name", "");
        if (Pattern.matches("Linux.*", osName)) {
            System.setProperty("prism.forceGPU", "true");
        }
        // Init & Launch
        AppConfig.init();
        launch();
    }

    @Override
    public void init() throws Exception {
        log.info("init");
        super.init();
        // 设置系统屏幕缩放比例
        try {
            var scaleX =  Screen.getScreens().get(0).getOutputScaleX();
            System.setProperty("glass.win.uiScale", String.valueOf(scaleX));
        } catch (Exception ignored) {
            System.setProperty("glass.win.uiScale", "1.0");
        }
        // 在非JavaFX应用程序主线程上运行指定的Runnable
        /*Platform.runLater(() -> {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setContentText("Content Text");
            alert.show();
        });*/
    }

    @Override
    public void start(Stage stage) throws IOException {
        log.info("start");
        // 加载并创建主场景
        Parent root = loadFXML("fxml/Main");
        scene = new Scene(root, AppConfig.stageWidth, AppConfig.stageHeight);
        // 设置窗口信息
        stage.setTitle(AppConfig.title);
        stage.setResizable(AppConfig.stageResizable);
        stage.getIcons().add(new Image(Objects.requireNonNull(App.class.getResourceAsStream(AppConfig.icon))));
        addMenu(stage);
        stage.setScene(scene);
        stage.show();
    }

    @Override
    public void stop() throws Exception {
        log.info("stop");
        try {
            final ApplicationService applicationService = SpringUtil.getBean(ApplicationService.class);
            applicationService.stop();
        } catch (Exception e) {
            log.error("error", e);
        }
        super.stop();
    }

    public static void setRoot(String fxml) throws IOException {
        scene.setRoot(loadFXML(fxml));
    }

    private static Parent loadFXML(String fxml) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
        return fxmlLoader.load();
    }

}
